module vga(
		input clk,
		input rstn,
		output vga_hs,
		output vga_vs,
		output  vga_r,
		output  vga_g,
		output  vga_b,
		input key1 //按键 key1
		);

//-----------------------------------------------------------//
// 水平扫描参数的设定 640*480 60Hz VGA
//-----------------------------------------------------------//
parameter LinePeriod =800; //行周期数e
parameter H_SyncPulse=96; //行同步脉冲（Sync a）
parameter H_BackPorch=48; //显示后沿（Back porch b）
parameter H_ActivePix=640; //显示时序段（Display interval c）
parameter H_FrontPorch=16; //显示前沿（Front porch d）
parameter Hde_start=144;
parameter Hde_end=784;
//-----------------------------------------------------------//
// 垂直扫描参数的设定 640*480  60Hz VGA
//-----------------------------------------------------------//
parameter FramePeriod =525; //列周期数s
parameter V_SyncPulse=2; //列同步脉冲（Sync o）
parameter V_BackPorch=33; //显示后沿（Back porch p）
parameter V_ActivePix=480; //显示时序段（Display interval q）
parameter V_FrontPorch=10; //显示前沿（Front porch r）
parameter Vde_start=35;
parameter Vde_end=515;
		
/*
//-----------------------------------------------------------//
// 水平扫描参数的设定 1024*768 60Hz VGA
//-----------------------------------------------------------//
parameter LinePeriod =1344; //行周期数
parameter H_SyncPulse=136; //行同步脉冲（Sync a）
parameter H_BackPorch=160; //显示后沿（Back porch b）
parameter H_ActivePix=1024; //显示时序段（Display interval c）
parameter H_FrontPorch=24; //显示前沿（Front porch d）
parameter Hde_start=296;
parameter Hde_end=1320;
//-----------------------------------------------------------//
// 垂直扫描参数的设定 1024*768 60Hz VGA
//-----------------------------------------------------------//
parameter FramePeriod =806; //列周期数
parameter V_SyncPulse=6; //列同步脉冲（Sync o）
parameter V_BackPorch=29; //显示后沿（Back porch p）
parameter V_ActivePix=768; //显示时序段（Display interval q）
parameter V_FrontPorch=3; //显示前沿（Front porch r）
parameter Vde_start=35;
parameter Vde_end=803;
*/
reg[9 : 0] x_cnt;
reg[9 : 0] y_cnt;
 reg[2: 0] grid_data_1;
 reg[2 : 0] grid_data_2;
 reg[2 : 0] bar_data;
 reg[3 : 0] vga_dis_mode;
 reg vga_r_reg;
 reg vga_g_reg;
 reg vga_b_reg; 
 reg hsync_r;
 reg vsync_r; 
 reg hsync_de;
 reg vsync_de;
 
 reg [19:0] key1_counter; //按键检测寄存器
 
 wire vga_clk; 
 wire [5:0] bar_interval;
 
assign bar_interval = H_ActivePix[8: 3]; //彩条宽度=H_ActivePix/8

  pll u1(
	.areset(~rstn),
	.inclk0(clk),
	.c0(vga_clk),
	.locked()
	);
//----------------------------------------------------------------
////////// 水平扫描计数
//----------------------------------------------------------------
always @ (posedge vga_clk)
begin
	if(~rstn) x_cnt <= 1;
	else if(x_cnt == LinePeriod) x_cnt <= 1;
	else x_cnt <= x_cnt+ 1;
end
//----------------------------------------------------------------
////////// 水平扫描信号 hsync,hsync_de 产生
//----------------------------------------------------------------
always @ (posedge vga_clk)
 begin
	if(~rstn) hsync_r <= 1'b1;
	else if(x_cnt == 1) hsync_r <= 1'b0; //产生 hsync 信号
	else if(x_cnt == H_SyncPulse) hsync_r <= 1'b1;
	
	if(1'b0) hsync_de <= 1'b0;
	else if(x_cnt == Hde_start) hsync_de <= 1'b1; //产生 hsync_de 信号
	else if(x_cnt == Hde_end) hsync_de <= 1'b0;
end
//----------------------------------------------------------------
////////// 垂直扫描计数
//----------------------------------------------------------------
always @ (posedge vga_clk)
begin
	if(~rstn) y_cnt <= 1;
	else if(y_cnt == FramePeriod) y_cnt <= 1;
	else if(x_cnt == LinePeriod) y_cnt <= y_cnt+1;
 end
 
//----------------------------------------------------------------
////////// 垂直扫描信号 vsync, vsync_de 产生
//----------------------------------------------------------------
always @ (posedge vga_clk)
 begin
	if(~rstn) vsync_r <= 1'b1;
	else if(y_cnt == 1) vsync_r <= 1'b0; //产生 vsync 信号
	else if(y_cnt == V_SyncPulse) vsync_r <= 1'b1;
 
	if(~rstn) vsync_de <= 1'b0;
	else if(y_cnt == Vde_start) vsync_de <= 1'b1; //产生 vsync_de 信号
	else if(y_cnt == Vde_end) vsync_de <= 1'b0;
 end
 
//----------------------------------------------------------------
////////// 格子测试图像产生
//----------------------------------------------------------------
always @(negedge vga_clk) 
 begin
	if ((x_cnt[5]==1'b1) ^ (y_cnt[5]==1'b1)) //产生小格子图像
	grid_data_1<= 3'b000;
 else
	grid_data_1<= 3'b111;
 if ((x_cnt[7]==1'b1) ^ (y_cnt[7]==1'b1)) //产生大格子图像
	grid_data_2<=3'b000;
 else
	grid_data_2<=3'b111; 
end

//----------------------------------------------------------------
////////// 彩色条测试图像产生
//----------------------------------------------------------------
always@(negedge vga_clk)
begin
	if(x_cnt==Hde_start)
				bar_data<=3'b100;			//红色
	else if(x_cnt==Hde_start+bar_interval)
				bar_data<=3'b010;			//绿色
	else if(x_cnt==Hde_start+bar_interval*2)
				bar_data<=3'b001;			//蓝色
	else if(x_cnt==Hde_start+bar_interval*3)
				bar_data<=3'b101;			//紫色
	else if(x_cnt==Hde_start+bar_interval*4)
				bar_data<=3'b011;			//黄色
	else if(x_cnt==Hde_start+bar_interval*5)
				bar_data<=3'b111;			//白色
	else if(x_cnt==Hde_start+bar_interval*6)
				bar_data<=3'b110;			//橙色
	else if(x_cnt==Hde_start+bar_interval*7)
				bar_data<=3'b000;			//黑色
end

//----------------------------------------------------------------
////////// VGA 图像选择输出
//----------------------------------------------------------------
//LCD 数据信号选择
always@(negedge vga_clk)
begin
	if(~rstn)begin
		vga_r_reg<=0;
		vga_g_reg<=0;
		vga_b_reg<=0;
	end
	else
		case(vga_dis_mode)
			4'd0:begin
				vga_r_reg<=0;			//VGA显示全黑
				vga_g_reg<=0;
				vga_b_reg<=0;
			end
			4'd1:begin
				vga_r_reg<=1;		//VGA显示全白
				vga_g_reg<=1;
				vga_b_reg<=1;
			end
			4'd2:begin
				vga_r_reg<=1;		//VGA显示全红
				vga_g_reg<=0;
				vga_b_reg<=0;
			end
			4'd3:begin
				vga_r_reg<=0;		//VGA显示全绿
				vga_g_reg<=1;
				vga_b_reg<=0;
			end
			4'd4:begin
				vga_r_reg<=1'b0;		//VGA显示全蓝
				vga_g_reg<=1'b0;
				vga_b_reg<=1'b1;
			end
			4'd5:begin
				vga_r_reg<=grid_data_1[2];		//VGA显示方格1
				vga_g_reg<=grid_data_1[1];
				vga_b_reg<=grid_data_1[0];
			end
			4'd6:begin
				vga_r_reg<=grid_data_1[2];		//VGA显示方格1
				vga_g_reg<=grid_data_1[1];
				vga_b_reg<=grid_data_1[0];
			end
			4'd7:begin
				vga_r_reg<=x_cnt[1]; //VGA 显示水平渐变色
				vga_g_reg<=x_cnt[2];
				vga_b_reg<=x_cnt[1];
			end
			4'd8:begin
				vga_r_reg<=y_cnt[1]; //VGA 显示垂直渐变色
				vga_g_reg<=y_cnt[2];
				vga_b_reg<=y_cnt[1];
			end
			4'd9:begin
				vga_r_reg<=x_cnt[1]; //VGA 显示水平渐变色
				vga_g_reg<=x_cnt[2];
				vga_b_reg<=x_cnt[1];
			end
		endcase
end

 assign vga_hs = hsync_r;
 assign vga_vs = vsync_r; 
 assign vga_r = (hsync_de & vsync_de)?vga_r_reg:0;
 assign vga_g = (hsync_de & vsync_de)?vga_g_reg:0;
 assign vga_b = (hsync_de & vsync_de)?vga_b_reg:0;
always @(posedge vga_clk)
 begin
	if(~rstn) begin 
		vga_dis_mode<=4'b0000; 
		key1_counter<=0;
	end
	else begin
		if (key1==1'b1) //如果按钮没有按下，寄存器为 0
			key1_counter<=0;
		else if ((key1==1'b0)& (key1_counter<=20'd90_000)) //如果按钮按下并按下时间少于 1ms,计数(9M*0.1=900_000) 
			key1_counter<=key1_counter+1'b1;
 
		if (key1_counter==20'd89_999) //一次按钮有效，改变显示模式
		begin
			if(vga_dis_mode==4'b1001)
				vga_dis_mode<=4'b0000;
			else
				vga_dis_mode<=vga_dis_mode+1'b1; 
		end
	end
end

endmodule

